#pragma once 

#include <iostream>
#include <functional> 
#include <string>
#include <strings.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include "InetAddr.hpp"

using namespace LogModule;
using func_t =std::function<std::string(const std::string&,const InetAddr&)>;
const int defaultfd=-1;

class UdpServer
{
    public:
        UdpServer(uint16_t port,func_t func)
        :_sockfd(defaultfd),
        _port(port),
        _func(func),
        _isrunning(false)
        {}
        void Init()
        {
            //1.创建套接字
            _sockfd=socket(AF_INET,SOCK_DGRAM,0);
            if(_sockfd<0)
            {
                LOG(LogLevel::FATAL)<<"socket error";
                exit(1);
            }
            LOG(LogLevel::INFO)<<"socket success"<<_sockfd;

            //2.绑定socket信息，ip和端口
            //2.1填写socketaddr_in结构体
            struct sockaddr_in local;
            bzero(&local ,sizeof(local));
            local.sin_family=AF_INET;
            //IP信息和端口信息，一定要发送到网络
            //本地格式-》网络格式
            local.sin_port=htons(_port);
            //local.sin_addr.s_addr=inet_addr(_ip.c_str());
            local.sin_addr.s_addr=INADDR_ANY;

            int n=bind(_sockfd,(struct sockaddr*)&local,sizeof(local));
            if(n<0)
            {
                LOG(LogLevel::FATAL)<<"bind error";
                exit(2);
            }
            LOG(LogLevel::INFO)<<"bind success,sockfd: "<<_sockfd;

        }
        void Start()
        {
            _isrunning=true;
            while(_isrunning)
            {
                char buffer[1024];
                struct sockaddr_in peer;
                socklen_t len=sizeof(peer);
                //1.收消息
                ssize_t s=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
                if(s>0)
                {
                    // int peer_port=peer.sin_port;
                    // std::string peer_ip=inet_ntoa(peer.sin_addr);
                    InetAddr client(peer);
                    buffer[s]=0;
                    std::string result =_func(buffer,client);
                    // LOG(LogLevel::DEBUG)<<"["<<peer_ip<<":"<<peer_port<<"]#"<<"buffer: "<<buffer;
                    // //2.发消息
                    // std::string echo_string="server echo@:";
                    // echo_string+=buffer;
                    sendto(_sockfd,result.c_str(),result.size(),0,(struct sockaddr*)&peer,len);
                }
            }
        }
        ~UdpServer()
        {}
    private:
        int _sockfd;
        //std::string _ip;
        uint16_t _port;
        bool _isrunning;

        func_t _func;//服务器的回调函数，用来对数据进行处理
};